package model;
/*
 * 
 * Attributs : il aura pour attribut son deck et sa corbeille qui seront des instanciations de la classe Pile, une main, une partieTerrain, 
 *            des ressources, des points de vie, l'attribut ressourceTemp se réinitialise à chaque début de tour et c'est lui qui permet de savoir combien le 
 *            le joueur consomme à poser des cartes
 * 
 * 
 * /!\ Méthode non définitive /!\ : jouerCarte()/poserCarte() : demande au joueur quelle carte posée, il regarde si elle est posable, 
 *                                                              puis lui demande à quel position la posée, puis il regarde si il n'y a pas de carte déja posée 
 *                                  choixAttaque()/lancerAttaque() : 2 méthodes qui font la même chose il lui demande si on attaque le joueur ou ses cartes
 *                                                                   puis retourne le choix du joueur si c'est 0 à 4 sa sera une des cartes défensives du terrain
 *                                                                   si c'est 5 on attaque le joueur (elle sert pas à grand chose vue que maintenant on a une IHM)
 *                                  séléctionnerAttaque() : on choisit la carte attaquante
 *                                  séléctionnerDefense() : on choisit la carte à attaquer
 *                                  choixJoueur()/choixJoueurV2() : organise le tour du joueur en offrant un choix au joueur en lui demandant quelle action faire
 *                                  passerTour() : monte les ressources de 1 et envoie une exception pour dire que le tour est terminé, 
 *                                                 l'exception sera traitée pas la classe Systeme (inutilisée)
 */

/**
 * Classe Joueur qui aura pour méthodes toutes les actions que le joueur pourra
 * réaliser. Elle implémente l'interface ObjetAttaquable.
 *
 * @author Antoine Thorr, Joana Santos, Samy Rida, Vicky Ngo Pagbe
 */
public class Joueur implements ObjetAttaquable {

    private Pile deck;
    private Pile corbeille;
    private Main main;
    private PartieTerrain partieTerrain;
    private int ressource;
    private int ressourceTemp;
    private int ptDeVie;
    private int ptDeVieBak;

    /**
     *
     */
    public Joueur() {
        this.deck = new Pile();
        this.main = new Main();
        this.partieTerrain = new PartieTerrain();
        this.corbeille = new Pile();
        this.ptDeVie = 20;
        this.ressource = 1;
        this.ressourceTemp = this.ressource;
    }

    /**
     * Contructeur de la classe. Permet de créer un Joueur et de lui affecter sa
     * main, ses ressources, son terrain, ses points de vies son Deck ainsi que
     * sa Corbeille.
     *
     * @param deck : Deck affecté au joueur.
     */
    public Joueur(Pile deck) {
        this.deck = deck;
        this.main = new Main();
        this.partieTerrain = new PartieTerrain();
        this.corbeille = new Pile();
        this.ptDeVie = 20;
        this.ressource = 1;
        this.ressourceTemp = this.ressource;
    }

    /**
     * Retourne le Deck du Joueur.
     *
     * @return Pile contenant le deckdu joueur.
     */
    public Pile getDeck() {
        return deck;
    }

    /**
     * Retourne la Corbeille du Joueur
     *
     * @return Pile contenant la corbeille du joueur.
     */
    public Pile getCorbeille() {
        return corbeille;
    }

    /**
     * Retourne la Main du joueur
     *
     * @return Main
     */
    public Main getMain() {
        return main;
    }

    /**
     * Retourne les points de vie du joueur
     *
     * @return points de vie
     */
    public int getPtDeVie() {
        return ptDeVie;
    }

    /**
     * Permet au joueur de piocher une carte dans son Deck. Si le Deck est vide
     * on lui affecte les cartes présente dans corbeille qu'on aura mélanger.
     */
    public void piocher() {
        if (this.deck.estVide()) {
            this.deck = new Pile(this.corbeille.getPileCarte());
            this.deck.melanger();
            for (Carte c : this.deck.getPileCarte()) {
                switch (c.getAttitude()) {
                    case "offensive":
                        CarteOffensive co = (CarteOffensive) c;
                        co.setVie(co.getVieBak());
                        break;
                    case "defensive":
                        CarteDefensive cd = (CarteDefensive) c;
                        cd.setVie(cd.getVieBak());
                        break;
                }
            }
            this.corbeille = new Pile();
        }
        this.main.piocher(this.deck.depiler());
    }

    /**
     * Permet de mettre le booléen de la Carte c à true, ce qui donnera le
     * signal au controlleur d'afficher la carte dans la selection.
     *
     *
     * @param c Carte à afficher
     */
    public void selection(Carte c) {           //Sélectionne la carte c dans notre main (appelée depuis la vue directement)
        for (Carte cb : this.main.getMain()) {
            if (c.getId() == cb.getId()) {
                c.setSelection(true);
            }
        }
    }

    /**
     * Regarde si on a une carte séléctionnée dans notre main (non utilsée)
     *
     * @return True si on a une carte séléctionnée, false sinon.
     */
    public boolean mainSelection() {
        for (Carte cb : this.main.getMain()) {
            if (cb.isSelection()) {
                return true;
            }
        }
        return false;

    }

    /**
     * Retourne la Carte séléctionnée par le joueur.
     *
     * @return Carte séléctionnée.
     */
    public Carte carteSelectionne() {
        for (Carte cb : this.main.getMain()) {
            if (cb.isSelection()) {
                return cb;
            }
        }
        for (Carte cb : this.partieTerrain.getAttaque()) {
            if (cb != null) {
                if (cb.isSelection()) {
                    return cb;
                }
            }

        }
        for (Carte cb : this.partieTerrain.getDefense()) {
            if (cb != null) {
                if (cb.isSelection()) {
                    return cb;
                }
            }
        }
        return null;
    }

    /**
     * Permet de piocher plusieurs cartes dans le Deck
     *
     * @param nombre : Nombre de cartes piochées
     */
    public void piocher(int nombre) {
        for (int i = 0; i < nombre; i++) {
            this.main.piocher(this.deck.depiler());
        }
    }

    /**
     * Permet de mettre la Carte c passé en paramètre à la corbeille
     *
     * @param c
     */
    public void defausser(Carte c) {
        this.corbeille.empiler(c);
        this.main.defausser(c);
    }

    /**
     * Retourne les ressources du joueur.
     *
     * @return ressources
     */
    public int getRessource() {
        return this.ressource;
    }

    /**
     * Permet d'affecter un nombre de ressources au joueur.
     *
     * @param ressource
     */
    public void setRessource(int ressource) {
        this.ressource = ressource;
        this.ressourceTemp = ressource;
    }

    /**
     * Retourne les ressources temporaires du joueur
     *
     * @return ressources temporaires
     */
    public int getRessourceTemp() {
        return this.ressourceTemp;
    }

    /**
     * Permet d'affecter un nombre de ressources temporaires au joueur.
     *
     * @param ressource
     */
    public void setRessourceTemp(int ressource) {
        this.ressourceTemp = ressource;
    }

    /**
     * Retourne la vie du joueur
     *
     * @return vie
     */
    @Override
    public int getVie() {
        return ptDeVie;
    }

    /**
     * Permet d'affecter une nouvelle vie au joueur
     *
     * @param ptDeVie
     */
    @Override
    public void setVie(int ptDeVie) {
        this.ptDeVie = ptDeVie;
    }

    /**
     * Retourne le nom de la classe.
     *
     * @return joueur
     */
    @Override
    public String getNomClasse() {
        return "joueur";
    }

    /**
     * Permet au joueur de poser une carte présente dans sa main sur son
     * terrain, si il reste assez de place sur la ligne. Puis lui enlève les
     * points de ressources correspondant.
     *
     * @param c Carte à poser.
     */
    public void poserCarte(Carte c) {
        switch (c.getAttitude()) {
            case "offensive":
                for (int i = 0; i < this.partieTerrain.getMaxLigneCartes(); i++) {
                    if (!this.partieTerrain.caseDejaPriseOff(i)) {
                        this.partieTerrain.placerOff((CarteOffensive) c, i);
                        this.ressourceTemp -= c.getCout();
                        break;
                    }
                }
                break;
            case "defensive":
                for (int i = 0; i < this.partieTerrain.getMaxLigneCartes(); i++) {
                    if (!this.partieTerrain.caseDejaPriseDef(i)) {
                        this.partieTerrain.placerDef((CarteDefensive) c, i);
                        this.ressourceTemp -= c.getCout();
                        break;
                    }
                }
                break;
        }
    }

    /**
     * Permet au joueur de poser une carte offensive présente dans sa main sur
     * son terrain, si il reste assez de place sur la ligne. Puis lui enlève les
     * points de ressources correspondant.
     *
     * @param c Carte à poser
     */
    public void poserCarteOffensive(CarteOffensive c) {
        for (int i = 0; i < 5; i++) {
            if (!this.partieTerrain.caseDejaPriseOff(i)) {
                this.partieTerrain.placerOff(c, i);
                this.ressourceTemp -= c.getCout();
                break;
            }
        }
        this.getMain().poser(c);
    }

    /**
     * Permet au joueur de poser une carte défensive présente dans sa main sur
     * son terrain, si il reste assez de place sur la ligne. Puis lui enlève les
     * points de ressources correspondant.
     *
     * @param c Carte à poser
     */
    public void poserCarteDefensive(CarteDefensive c) {
        for (int i = 0; i < 5; i++) {
            if (!this.partieTerrain.caseDejaPriseDef(i)) {
                this.partieTerrain.placerDef(c, i);
                this.ressourceTemp -= c.getCout();
                break;
            }
        }
        this.getMain().poser(c);
    }

    /**
     * Retourne le terrain du joueur
     *
     * @return PartieTerrain
     */
    public PartieTerrain getPartieTerrain() {
        return partieTerrain;
    }

    /**
     * Permet de mettre de mettre les ressources à jour lorsque le joueur passe
     * son tour
     */
    public void passerTour() {
        this.setRessource(ressource++);
    }

    /**
     * Permet de mettre à jour l'état de la carte en mettant qu'elle est
     * enAttente, elle ne pourra donc attaquer qu'au tour suivant.
     */
    public void upEtatCarte() {
        for (CarteOffensive attaque : this.partieTerrain.getAttaque()) {
            if (attaque != null) {
                attaque.setEtat(Etat.enAttente);
            }
        }
    }

    /**
     * Permet d'augmenter les ressources du joueur de 1 et de mettre son état en
     * attente.
     */
    public void upRessource() {
        this.ressource++;
        this.ressourceTemp = this.ressource;
        upEtatCarte();
    }

    /**
     * Permet de placer la Carte c passé en paramètre dans la Corbeille du
     * joueur.
     *
     * @param c Carte à placer dans la Corbeille.
     */
    public void aLaCorbeille(Carte c) {
        if (c.getAttitude().equals("offensive")) {
            for (int i = 0; i < this.partieTerrain.getAttaque().length; i++) {
                //CarteOffensive co = this.partieTerrain.getAttaque()[i];
                if (this.partieTerrain.getAttaque()[i] != null) {
                    if (c.getId() == this.partieTerrain.getAttaque()[i].getId()) {
                        this.corbeille.empiler(c);
                        this.partieTerrain.getAttaque()[i] = null;
                        return;
                    }
                }
            }
        } else if (c.getAttitude().equals("defensive")) {
            for (int i = 0; i < this.partieTerrain.getDefense().length; i++) {
                //CarteDefensive cd = this.partieTerrain.getDefense()[i];
                if (this.partieTerrain.getDefense()[i] != null) {
                    if (c.getId() == this.partieTerrain.getDefense()[i].getId()) {
                        this.corbeille.empiler(c);
                        this.partieTerrain.getDefense()[i] = null;
                        return;
                    }
                }

            }
        }
    }

    @Override
    public int getVieBak() {
        return this.ptDeVieBak;
    }
}
